//
// (C) Copyright 2009 Irantha Suwandarathna (irantha@gmail.com)
// All rights reserved.
//

/* Copyright (c) 2001-2008, The HSQL Development Group
 * All rights reserved.
 *
 * Redistribution and use _in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * Redistributions of source code must retain the above copyright notice, this
 * list of conditions and the following disclaimer.
 *
 * Redistributions _in binary form must reproduce the above copyright notice,
 * this list of conditions and the following disclaimer _in the documentation
 * and/or other materials provided with the distribution.
 *
 * Neither the name of the HSQL Development Group nor the names of its
 * contributors may be used to endorse or promote products derived from this
 * software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL HSQL DEVELOPMENT GROUP, HSQLDB.ORG,
 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */


using System;
using EffiProz.Core.Lib;
using EffiProz.Core.DataTypes;
using EffiProz.Core.Errors;
using EffiProz.Core.Persist;

namespace EffiProz.Core.RowIO
{



    /**
     *  Class for reading the data for a database row _in text table format.
     *
     * @author sqlbob@users (RMP)
     * @version 1.8.0
     * @since 1.7.0
     */
    public class RowInputText : RowInputBase, RowInputInterface
    {
        // text table specific
        private String fieldSep;
        private String varSep;
        private String longvarSep;
        private int fieldSepLen;
        private int varSepLen;
        private int longvarSepLen;
        private bool fieldSepEnd;
        private bool varSepEnd;
        private bool longvarSepEnd;
        private int textLen;
        protected String text;
        protected int line;
        protected int field;
        protected int next = 0;
        protected bool allQuoted;
        protected Scanner scanner;

        /**
         * fredt@users - comment - in future may use a custom subclasse of
         * InputStream to read the data.
         */
        public RowInputText(String fieldSep, String varSep, String longvarSep,
                            bool allQuoted)
            : base(new byte[0])
        {



            scanner = new Scanner();

            //-- Newline indicates that field should match to end of line.
            if (fieldSep.EndsWith("\n"))
            {
                fieldSepEnd = true;
                fieldSep = fieldSep.Substring(0, fieldSep.Length - 1);
            }

            if (varSep.EndsWith("\n"))
            {
                varSepEnd = true;
                varSep = varSep.Substring(0, varSep.Length - 1);
            }

            if (longvarSep.EndsWith("\n"))
            {
                longvarSepEnd = true;
                longvarSep = longvarSep.Substring(0, longvarSep.Length - 1);
            }

            this.allQuoted = allQuoted;
            this.fieldSep = fieldSep;
            this.varSep = varSep;
            this.longvarSep = longvarSep;
            fieldSepLen = fieldSep.Length;
            varSepLen = varSep.Length;
            longvarSepLen = longvarSep.Length;
        }

        public virtual void setSource(String text, int pos, int byteSize)
        {

            size = byteSize;
            this.text = text;
            textLen = text.Length;
            filePos = pos;
            next = 0;

            line++;

            field = 0;
        }

        protected virtual String getField(String sep, int sepLen,
                                  bool isEnd)
        {

            String s = null;

            try
            {
                int start = next;

                field++;

                if (isEnd)
                {
                    if ((next >= textLen) && (sepLen > 0))
                    {
                        throw Error.error(ErrorCode.TEXT_SOURCE_NO_END_SEPARATOR);
                    }
                    else if (text.EndsWith(sep))
                    {
                        next = textLen - sepLen;
                    }
                    else
                    {
                        throw Error.error(ErrorCode.TEXT_SOURCE_NO_END_SEPARATOR);
                    }
                }
                else
                {
                    next = text.IndexOf(sep, start);

                    if (next == -1)
                    {
                        next = textLen;
                    }
                }

                if (start > next)
                {
                    start = next;
                }

                s = text.Substring(start, next - start);
                next += sepLen;
                s = s.Trim();

                if (s.Length == 0)
                {
                    s = null;
                }
            }
            catch (Exception e)
            {
                throw new System.IO.IOException(
                    Error.getMessage(
                        ErrorCode.M_TEXT_SOURCE_FIELD_ERROR, 0, new Object[] {
                field, e.ToString()
            }));
            }

            return s;
        }

        public override String readString()
        {
            return getField(fieldSep, fieldSepLen, fieldSepEnd);
        }

        private String readVarString()
        {
            return getField(varSep, varSepLen, varSepEnd);
        }

        /**
         * Obsoleted in 1.9.0
         */
        private String readLongVarString()
        {
            return getField(longvarSep, longvarSepLen, longvarSepEnd);
        }

        public override short readShort()
        {
            return (short)readInt();
        }

        public override int readInt()
        {

            String s = readString();

            if (s == null)
            {
                return 0;
            }

            s = s.Trim();

            if (s.Length == 0)
            {
                return 0;
            }

            return int.Parse(s);
        }

        public override long readLong()
        {
            throw Error.runtimeError(ErrorCode.U_S0500, "RowInputText");
        }

        public override int readType()
        {
            return 0;
        }

        protected override bool checkNull()
        {

            // Return null on each column read instead.
            return false;
        }

        protected override String readChar(SqlType type)
        {

            switch (type.typeCode)
            {

                case Types.SQL_CHAR:
                    return readString();

                case Types.SQL_VARCHAR:
                case Types.VARCHAR_IGNORECASE:
                    return readVarString();

                default:
                    return readLongVarString();
            }
        }

        protected override int? readSmallint()
        {

            String s = readString();

            if (s == null)
            {
                return null;
            }

            s = s.Trim();

            if (s.Length == 0)
            {
                return null;
            }

            return int.Parse(s);
        }

        protected override int? readInteger()
        {

            String s = readString();

            if (s == null)
            {
                return null;
            }

            s = s.Trim();

            if (s.Length == 0)
            {
                return null;
            }

            return int.Parse(s);
        }

        protected override long? readBigint()
        {

            String s = readString();

            if (s == null)
            {
                return null;
            }

            s = s.Trim();

            if (s.Length == 0)
            {
                return null;
            }

            return long.Parse(s);
        }

        protected override double? readReal()
        {

            String s = readString();

            if (s == null)
            {
                return null;
            }

            s = s.Trim();

            if (s.Length == 0)
            {
                return null;
            }

            return double.Parse(s);
        }

        protected override decimal? readDecimal(SqlType type)
        {

            String s = readString();

            if (s == null)
            {
                return null;
            }

            s = s.Trim();

            if (s.Length == 0)
            {
                return null;
            }

            return decimal.Parse(s);
        }

        protected override TimeData readTime(SqlType type)
        {

            String s = readString();

            if (s == null)
            {
                return null;
            }

            s = s.Trim();

            if (s.Length == 0)
            {
                return null;
            }

            return scanner.newTime(s);
        }

        protected override TimestampData readDate(SqlType type)
        {

            String s = readString();

            if (s == null)
            {
                return null;
            }

            s = s.Trim();

            if (s.Length == 0)
            {
                return null;
            }

            return scanner.newDate(s);
        }

        protected override TimestampData readTimestamp(SqlType type)
        {

            String s = readString();

            if (s == null)
            {
                return null;
            }

            s = s.Trim();

            if (s.Length == 0)
            {
                return null;
            }

            return scanner.newTimestamp(s);
        }

        protected override IntervalMonthData readYearMonthInterval(SqlType type)
        {

            String s = readString();

            if (s == null)
            {
                return null;
            }

            s = s.Trim();

            if (s.Length == 0)
            {
                return null;
            }

            return (IntervalMonthData)scanner.newInterval(s, (IntervalType)type);
        }

        protected override IntervalSecondData readDaySecondInterval(SqlType type)
        {

            String s = readString();

            if (s == null)
            {
                return null;
            }

            s = s.Trim();

            if (s.Length == 0)
            {
                return null;
            }

            return (IntervalSecondData)scanner.newInterval(s,
                    (IntervalType)type);
        }

        protected override bool? readBoolean()
        {

            String s = readString();

            if (s == null)
            {
                return null;
            }

            s = s.Trim();

            if (s.Length == 0)
            {
                return null;
            }
            return s.EndsWith(Tokens.T_TRUE, StringComparison.OrdinalIgnoreCase) ? true
                                              : false;
        }

        protected override Object readOther()
        {

            String s = readString();

            if (s == null)
            {
                return null;
            }

            BinaryData data = scanner.convertToBinary(s);

            if (data.length(null) == 0)
            {
                return null;
            }

            return new OtherData(data.getBytes());
        }

        protected override BinaryData readBit()
        {

            String s = readString();

            if (s == null)
            {
                return null;
            }

            BinaryData data = scanner.convertToBit(s);

            return data;
        }

        protected override BinaryData readBinary()
        {

            String s = readString();

            if (s == null)
            {
                return null;
            }

            BinaryData data = scanner.convertToBinary(s);

            return data;
        }

        protected override ClobData readClob()
        {

            String s = readString();

            if (s == null)
            {
                return null;
            }

            s = s.Trim();

            if (s.Length == 0)
            {
                return null;
            }

            long id = long.Parse(s);

            return new ClobDataID(id);
        }

        protected override BlobData readBlob()
        {

            String s = readString();

            if (s == null)
            {
                return null;
            }

            s = s.Trim();

            if (s.Length == 0)
            {
                return null;
            }

            long id = long.Parse(s);

            return new BlobDataID(id);
        }

        public int getLineNumber()
        {
            return line;
        }

        public void skippedLine()
        {
            line++;
        }

        public override void reset()
        {

            text = "";
            textLen = 0;
            filePos = 0;
            next = 0;
            field = 0;
            line = 0;
        }
    }
}
